#ifndef SEU_TORRENT_H
#define SEU_TORRENT_H

typedef enum {
   STAT_COMPLETING,//Transitioning from leech to complete
   STAT_COMPLETE,//100% and essentially stopped
   STAT_SEEDING, //100% but active
   STAT_STARTING,//In the middle of announcing for the first time
   STAT_LEECHING,//Downloading data
   STAT_PAUSED,  //User paused it
   STAT_STOPPING,//In the middle of stopping
   STAT_STOPPED, //User stopped it
} STATUS;


typedef struct {
   char *name; //Filename
   unsigned long len; //Length in bytes
   char *md5sum; //Yeah right, like anyone'll give us this optional item
} sfile; //Single file torrent filedata

typedef struct {
   char *name; //Base path to files
   list_t *files; //List of sfile's
} mfile; //Multifile torrent filedata

typedef struct {
   short priv; //private torrent, bool

   unsigned long pieceLen; //Bytes in a piece
			   //Long to support 4 GB pieces... wait what?
   unsigned char *infohash; //Always 20 len
   char *pieces; //Piece string
   unsigned long long piecesLen; //Piece string length
   unsigned long long totalSize; //Can technically be calculated anyways. pieceLen * piecesLen/20

   char *announce; //announce url. 

   short singleFile; //single or multi, bool
   union {
      sfile *s;
      mfile *m;
   } file;

   //Extra info on progress and stuff
   unsigned long long downloaded;//bytes
   unsigned long long uploaded;  //bytes
   unsigned long long left;
   bitfield_t *piecebitfield;
   dict_t *activeReqs; //key is ndx, val is bitfield
   //We need both of these. One keeps track of what we've asked for,
   //the other keeps track of what we asked for AND GOT BACK
   dict_t *activeReqsRcved; //key is ndx, val is bitfield
   STATUS status;

   unsigned int totalSeeders;    //As reported by the tracker
   unsigned int totalLeechers;	 //As reported by the tracker

   list_t *inactpeers;    //Given out by the tracker
   list_t *actpeers;	//Peers I'm actually communicating with
   
   unsigned int lastPeerShuffle;
   unsigned int shuffleInterval;

   unsigned int lastAnnounce;
   unsigned int announceInterval;
   unsigned int minAnnounceInterval;

} torrent_t;

torrent_t *torrentInit (list_t *bedat);

int torrentTrackerAnnounce(torrent_t *t, char *peer_id, int port);
void torrentAnnounceIfNeeded(torrent_t *t, char *peer_id, int port);
void torrentForceAnnounce(torrent_t *t, char *peer_id, int port); //Used for STOPPING event mainly.
void torrentKeepPeersAlive(torrent_t *t);
void torrentShufflePeers(torrent_t *t, char *peer_id);
void torrentActivatePeer(torrent_t *t, char *peer_id);
void torrentDeactivatePeer(torrent_t *t, peer_t *p);

void torrentIncreaseDownloaded(torrent_t *t, unsigned int len);

void torrentCheckForData(torrent_t *t);
void torrentReceiveBlock(torrent_t *t, unsigned int ndx, unsigned int offset, unsigned char *data, unsigned int len);
void torrentRequestBlocks(torrent_t *t);

void torrentSendPieces(torrent_t *t); // Check for requests, send out data

void torrentPeerEventCallback(torrent_t *t, peer_t *p, netmsg_t msg);

void torrentHavePiece(torrent_t *t, unsigned int ndx);

char *torrentGetName(torrent_t *t);

char *torrentStatusString(torrent_t *t);
double torrentDownloaded(torrent_t *t);

void torrentPrint(torrent_t *t);

#endif
